package com.dq.controller.api.pay;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dq.context.config.WxMaConfiguration;
import com.dq.exception.customException.AdminException;
import com.dq.exception.customException.ApiException;
import com.dq.domain.activity.ActivityRecord;
import com.dq.domain.orders.Orders;
import com.dq.domain.orders.UserOrder;
import com.dq.domain.orders.info.OrderInfo;
import com.dq.domain.service.ServiceProject;
import com.dq.domain.service.centre.WxUserServiceProjectCentre;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.domain.sys.user.user.WxUser;
import com.dq.service.AllService;
import com.dq.utils.TimeUtil;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import io.swagger.annotations.ApiOperation;
import lombok.extern.java.Log;
import okhttp3.OkHttpClient;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("api/pay/wx")
@ApiIgnore
@Log
public class ApiWxAppPayController extends AllService {

    @Autowired
    ApplicationEventPublisher eventPublisher;

    private Logger logger = LoggerFactory.getLogger(ApiWxAppPayController.class);

    @Value("${api.wx.small.notify.url}")
    public String small_notify_url;

    public static String version = "1.0";

    public WxPayUnifiedOrderResult smallTradePay(String ordersNo) throws ApiException {
        SysUser user = shiroService.getUser();
        WxUser wxUser = dao.get(WxUser.class,user.getId());
        if (null == user) {
            throw new ApiException("用户信息获取失败");
        }
        UserOrder orders = userOrderRepository.getByOrdersNo(ordersNo);
        if (null == orders) {
            throw new ApiException("支付中查询订单信息失败，请联系管理员");
        }
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest(version, "WAP", "您正在使用微信支付",
                "测试", "商品购买", ordersNo, "CNY", orders.getPrice().multiply(new BigDecimal(100)).intValue(),
                "172.1.1.1", TimeUtil.longToString(System.currentTimeMillis(), TimeUtil.YYYYMMDDHHMMSS), TimeUtil.longToString(orders
                .getOrdersPayCountDownTime(), TimeUtil.YYYYMMDDHHMMSS), "普通", small_notify_url, "JSAPI",
                orders.getId() + "", "", wxUser.getOpenid(), "", "Y", "", "");
        try {
            WxPayUnifiedOrderResult wxPayUnifiedOrderResult = WxMaConfiguration.getWxPayService().unifiedOrder(wxPayUnifiedOrderRequest);
            String timeTmep = System.currentTimeMillis() + "";
            String signTemp = "appId=" + WxMaConfiguration.getAppId() + "&nonceStr=" + RandomStringUtils.randomAlphabetic
                    (32) + "&package=\"prepay_id=" + wxPayUnifiedOrderResult.getPrepayId() + "\"&signType=MD5&timeStamp="
                    + timeTmep.substring(0, timeTmep.length() - 3) + "&key=" + WxMaConfiguration.getKey();
            String sign = md5(signTemp).toUpperCase();
            wxPayUnifiedOrderResult.setSign(sign);
            return wxPayUnifiedOrderResult;
        } catch (WxPayException e) {
            throw new ApiException("付款失败");
        }
    }

    public static String md5(String key) {
        char hexDigits[] = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };
        try {
            byte[] btInput = key.getBytes();
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

    @ApiOperation("小程序支付回调")
    @PostMapping("/notify/small")
    public String smallOrderNotify(@RequestBody String str) throws AdminException {
        logger.info("接收到小程序微信支付notify:" + str);
        Map map = SignMd5.xmlString2Map(str);
        logger.info("转换后的map:" + map);
        if ("SUCCESS".equals(map.get("return_code").toString())) {
            String orderNo = map.get("out_trade_no").toString();
            UserOrder order = userOrderRepository.getByOrdersNo(orderNo.trim());
            if ("SUCCESS".equals(map.get("result_code").toString())) {
                log.info(map.get("transaction_id").toString() + "支付成功...");
                //订单逻辑
                order.setStatus(UserOrder.UserOrderStatus.waitCheckOut);
                userOrderRepository.save(order);
                //活动订单逻辑
                if(UserOrder.OrderSource.activity.equals(order.getOrderSource())){
                    WxUser wxUser = (WxUser) order.getWxUser();
                    wxUser.setMemberType(WxUser.MemberType.experience);
                    wxUser.setSection(order.getOrg());
                    sysUserRepository.save(wxUser);
                    ActivityRecord activityRecord = new ActivityRecord();
                    Orders orders = ordersRepository.getByOrdersNo(orderNo);
                    OrderInfo orderInfo = orderInfoRepository.findByOrdersAndDeletedFalse(orders);
                    activityRecord.setActivity(orderInfo.getActivity());
                    activityRecord.setSysUser(wxUser);
                    activityRecord.setSysDept(order.getOrg());
                    activityRecordRepository.save(activityRecord);
                    String project = activityRecord.getActivity().getServiceProject();
                    JSONArray jsonArray = JSONArray.parseArray(project);
                    List<WxUserServiceProjectCentre> wxUserServiceProjectCentres = new ArrayList<>();
                    for (int i = 0; i < jsonArray.size(); i++) {
                        JSONObject jsonInfo = (JSONObject) jsonArray.get(i);
                        if("".equals(jsonInfo.get("value")) && jsonInfo.get("value") != null){
                            ServiceProject serviceProject = serviceProjectRepository.findByProjectNameAndDeletedFalse(jsonInfo.get("value").toString());
                            WxUserServiceProjectCentre wxUserServiceProjectCentre = wxUserServiceProjectCentreRepository.findByDeletedFalseAndWxUserAndServiceProject(wxUser,serviceProject);
                            if(wxUserServiceProjectCentre == null){
                                wxUserServiceProjectCentre = new WxUserServiceProjectCentre();
                                wxUserServiceProjectCentre.setWxUser(wxUser);
                                wxUserServiceProjectCentre.setServiceProject(serviceProject);
                                wxUserServiceProjectCentre.setNum(Long.parseLong(jsonInfo.get("num").toString()));
                            }else {
                                wxUserServiceProjectCentre.setNum(wxUserServiceProjectCentre.getNum()+Long.parseLong(jsonInfo.get("num").toString()));
                            }
                            wxUserServiceProjectCentres.add(wxUserServiceProjectCentre);
                        }
                    }
                    wxUserServiceProjectCentreRepository.saveAll(wxUserServiceProjectCentres);
                }
                TreeMap<String, String> treeMap = new TreeMap();
                treeMap.put("return_code", "SUCCESS");
                treeMap.put("return_msg", "OK");
                try {
                    String xml = SignMd5.mapToXml(treeMap);
                    log.info("返回xml：" + xml);
                    return xml;
                } catch (Exception e) {
                    return "fail";
                }
            }
        }
        return "fail";
    }


    @Bean
    public OkHttpClient createOkHttpClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(120, TimeUnit.SECONDS).readTimeout(120, TimeUnit.SECONDS)
                .writeTimeout(120, TimeUnit.SECONDS).retryOnConnectionFailure(true);
        return builder.build();
    }

}